import os
import sys
import ctypes
import platform
import subprocess
from functools import wraps


def require_admin(func):
    """
    管理员权限装饰器
    用法：
    @require_admin
    def main():
        # 需要管理员权限的操作
    """

    @wraps(func)
    def wrapper(*args, **kwargs):
        if not is_admin():
            print("正在请求管理员权限...")
            restart_as_admin()
            sys.exit()
        return func(*args, **kwargs)

    return wrapper


def is_admin():
    """检查当前是否具有管理员权限"""
    try:
        # Linux/macOS 系统检查
        if os.getuid() == 0:
            return True
    except AttributeError:
        # Windows 系统检查
        try:
            return ctypes.windll.shell32.IsUserAnAdmin() != 0
        except:
            return False
    return False


def restart_as_admin():
    """以管理员权限重启当前脚本"""
    system = platform.system()
    script = sys.argv[0]

    if system == "Windows":
        # Windows 使用ShellExecute实现UAC提权
        ctypes.windll.shell32.ShellExecuteW(
            None,
            "runas",
            sys.executable,
            f'"{script}"' + ' ' + subprocess.list2cmdline(sys.argv[1:]),
            None,
            1
        )
    elif system == "Linux":
        # Linux 使用pkexec图形化提权
        if _check_pkexec():
            os.execvp("pkexec", ["pkexec", sys.executable, script] + sys.argv[1:])
        else:
            # 命令行sudo提权
            os.execvp("sudo", ["sudo", sys.executable, script] + sys.argv[1:])
    elif system == "Darwin":
        # macOS 使用osascript触发图形化提权
        applescript = f'''
        do shell script "python3 '{script}' {subprocess.list2cmdline(sys.argv[1:])}" 
        with administrator privileges
        '''
        subprocess.run(
            ["osascript", "-e", applescript],
            check=True
        )
    else:
        raise OSError("不支持的操作系统")


def _check_pkexec():
    """检查是否可用pkexec"""
    try:
        subprocess.run(
            ["pkexec", "--version"],
            stdout=subprocess.DEVNULL,
            stderr=subprocess.DEVNULL
        )
        return True
    except (FileNotFoundError, subprocess.CalledProcessError):
        return False


@require_admin
def update_dns_flush():
    """执行curl命令并更新界面显示"""
    host = "https://raw.hellogithub.com/hosts"
    try:
        # 根据不同系统设置ping参数
        if sys.platform.startswith('win'):
            curl_cmd = ['curl', '-n', '1', host]
            encoding = 'gbk'
        else:
            curl_cmd = ['curl', '-c', '1', host]
            encoding = 'utf-8'

        # 执行ping命令
        result = subprocess.run(
            curl_cmd,
            capture_output=True,
            text=True,
            encoding=encoding,
            timeout=5
        )
        new_content = result.stdout
        file_path = r"C:\Windows\System32\drivers\etc\hosts"
        # 读取原始文件内容
        with open(file_path, 'r', encoding='utf-8') as f:
            original_lines = f.readlines()

        # 处理前29行
        preserved_lines = original_lines[:29]

        # 如果原文件不足29行，用空行补齐
        if len(preserved_lines) < 29:
            preserved_lines += ['\n'] * (29 - len(preserved_lines))
        # 处理新内容（自动保留原始换行符）
        new_lines = []
        if new_content:
            # 拆分新内容为行列表
            temp_lines = new_content.splitlines(keepends=True)
            # 如果没有自带换行符则自动添加
            if not new_content.endswith(('\n', '\r', '\r\n')):
                temp_lines[-1] += '\n'
            new_lines = temp_lines
        # 合并内容
        final_content = preserved_lines + new_lines
        # 写入文件
        with open(file_path, 'w', encoding='utf-8') as f:
            f.writelines(final_content)
        # 更新界面显示
        subprocess.run(["ipconfig", "/flushdns"], check=True)
        print(f"文件 {file_path} 已成功更新")
    except Exception as e:
        print(f"发生未知错误：{str(e)}")
    return False
if __name__ == '__main__':
    update_dns_flush()
    input("按回车键退出...")